/*
 * CGbtDeviceAgent.h
 *
 *  Created on: 2018年5月20日
 *      Author: zhengboyuan
 */

#ifndef CGBTDEVICEAGENT_H_
#define CGBTDEVICEAGENT_H_

#include "GbtDeviceAgent.h"
#include "SipAgent.h"
#include <map>
#include "GbtMediaDeviceMap.h"
#include "TMap.h"
#include "MediaSessionMap.h"
#include "Sdp.h"
#include "RtpType.h"

#include "SubscriptionCatalogMap.h"
#include "SubscriptionAlarmMap.h"
#include "SubscriptionPositionMap.h"

#include "TimerQueue.h"
#include "HttpServer.h"
#include "RtpMediaChannelFactory.h"


namespace gbt
{

class CGbtDeviceAgent: public GbtDeviceAgent,
                       public SipAgentSink,
                       public InviteSessionHandler,
                       public SubscriptionSessionHandler,
                       public GbtMediaDeviceHandler,
                       public HttpHandler,
                       public MediaSession::Sink,
                       public comn::TimerHandler
{
public:
    CGbtDeviceAgent();
    virtual ~CGbtDeviceAgent();

    virtual void setHeartBeat(int seconds, int timeout);

    virtual void setRegTime(int seconds);

    virtual void setRtpPort(uint16_t minPort, uint16_t maxPort);

    virtual void setUserAgent(const char* name);

    virtual void setCatalog(const GBT_Catalog& catalog);

    virtual void setPosition(const GBT_Position& position);


    virtual int open(const char* ip, int port, const GBT_Server& server);

    virtual void close();

    virtual bool isOpen();

    virtual bool setServer(const GBT_Server& server);

    virtual bool isConnected();

	virtual const char* getContact();

    virtual void refreshReg();

    virtual void setSink(GbtDeviceAgentSink* sink);


    virtual GbtMediaDevice* createDevice(int id, const char* deviceID);

    virtual void destroyDevice(GbtMediaDevice* device);


    virtual void setMessageHandler(GbtDeviceMessageHandler* handler);

    virtual bool sendOutAlarm(const GBT_Alarm& alarm);

    virtual bool sendMessage(const char* deviceID, const char* content, size_t length);

    virtual bool sendResponseResult(const char* deviceID, const char* cmdType, int sn, int result);


    virtual bool addHttpDir(const char* dirPath, const char* urlPath);

    virtual int startHttp(uint16_t port, const char* webroot);

    virtual void stopHttp();

    virtual void setPlaybackHandler(GbtDevicePlaybackHandler* handler);
    virtual void closePlaybacks(const char* deviceID);
    virtual void closePlays(const char* deviceID);

    virtual bool setParam(GbtDeviceParam name, const char* value);

    virtual void enableReconnection(bool enabled);

    virtual void setHostAddr(const char* ip);

    virtual void setTransport(GBT_Transport transport);

	virtual const char* findDeviceID(int id);

	virtual bool findDeviceNum(const char* deviceID, int& id);


    void setTalkTransport(GBT_Transport transport);


protected:
    virtual void handleStatus(GbtMediaDeviceEx* device, bool isOnline);

    virtual void handlePosition(GbtMediaDeviceEx* device, const GBT_Position& position);

    virtual bool onTimer(const comn::TimerID& id, uint32_t& interval);

    virtual int handleJsonApi(HttpRequest& request, std::string& json);
    virtual void handleUpload(const char* name, const std::string& filepath);
    virtual int handleFileApi(HttpRequest& request, std::string& resp, std::string& mime);
    virtual void handleWebSocketFrame(unsigned char *data, size_t size, unsigned char flags);

protected:
    virtual void onConnectionStatus(bool connected, int64_t clock);

    virtual bool onCommand(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);

    virtual void onMessageNew(const char* fromUri, const char* mime, const char* body, size_t length);


    virtual bool onInSubscriptionNew(int sid, int tid, tinyxml2::XMLDocument& doc, const GBT_Command& query);

    virtual void onSubscriptionEnd(int sid);

    virtual void onSubscriptionAnswered(int sid);

    virtual void onSubscriptionNotify(int sid, tinyxml2::XMLDocument& doc, const GBT_Command& query);


    virtual void onInviteNew(InviteSessionHandle handle, const InviteSession& session, const char* body, size_t length);
    virtual void onInviteAck(InviteSessionHandle handle, const char* body, size_t length);
    virtual void onInviteAnswered(InviteSessionHandle handle, const char* body, size_t length);
    virtual void onInviteClosed(InviteSessionHandle handle);
    virtual void onInviteReleased(InviteSessionHandle handle);
    virtual void onInviteMessage(InviteSessionHandle handle, const char* body, size_t length);



    ///
    virtual void onMediaEvent(MediaSession* session, int event);

protected:
    typedef bool (CGbtDeviceAgent::*CommandHandler)(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    typedef std::map< std::string, CommandHandler > CommandHandlerMap;

    void setupHandlerMap();

    bool onCommandCatalog(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandDeviceControl(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandDeviceConfig(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandDeviceStatus(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandDeviceInfo(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandQueryRecordInfo(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandQueryAlarm(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandConfigDownload(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandPresetQuery(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandMobilePosition(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);

    bool onCommandPtzCmd(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandTeleBoot(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandRecordCmd(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandAlarmCmd(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandGuardCmd(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandIFrameCmd(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandDragZoomIn(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandDragZoomOut(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);
    bool onCommandSetHomePosition(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);

    bool onCommandBroadcast(tinyxml2::XMLDocument& doc, const GBT_Command& request, std::string& resp);

protected:
    bool isCommand(const GBT_Command& request, const char* cmdType);

    const char* getSelfUnicode();

    bool findVideoMedium(sdp::SessionDescription& sdp, RtpMedium& rtpMedium);
    bool findAudioMedium(sdp::SessionDescription& sdp, RtpMedium& rtpMedium);
    av::RtpProtocol getRtpProtocol(const RtpMedium& medium);

    std::string getMediaAddr();

    std::string makePlayAnswer(MediaSessionPtr& mediaSession);
    std::string makeTalkAnswer(MediaSessionPtr& mediaSession);

    void publishCatalogs(int did);

    void publishCatalog(GbtMediaDeviceEx& device, bool isOnline);
    void publishCatalog(const GBT_Catalog& catalog);


    void cleanupOnDisconnected();

    void clearSubs();

    bool makeErrorResult(const GBT_Command& request, std::string& resp);

	std::string makeHttpUrl();

	void onInviteNewLive(InviteSessionHandle handle, const InviteSession& session, GbtMediaDeviceExPtr& device, RtpMedium& rtpMedium, SessionInfo& sessionInfo);
	void onInviteNewTalk(InviteSessionHandle handle, const InviteSession& session, GbtMediaDeviceExPtr& device, RtpMedium& rtpMedium, SessionInfo& sessionInfo);
    void onInviteNewRecord(InviteSessionHandle handle, const InviteSession& session, GbtMediaDeviceExPtr& device, RtpMedium& rtpMedium, SessionInfo& sessionInfo);

	GbtMediaDeviceExPtr findTalkDevice(const char* deviceID);

	bool startTalk(GbtMediaDeviceExPtr& device, const char* userID, const char* targetID);
	std::string makeTalkOffer(av::RtpProtocol protocol, av::RtpMediaChannelPtr& mediaChannel, GbtMediaDeviceExPtr& device, const char* userID, const char* targetID);

	void sendOutPosition(const std::string& deviceID);
	void sendOutPosition(GbtMediaDeviceExPtr& device);
	void sendOutPosition(const char* deviceID, const GBT_Position& position);
    bool publishPosition(const char* deviceID, const GBT_Position& position);

	void addRootCatalog(GBT_CatalogArray& catalogs);

	void initRootCatalog(const char* ip, int port, const char* deviceID);


    
    int openPlayback(const GBT_RecordUrl& record, double speed, MStreamSource** ppStream);
    void closePlayback(MStreamSource* pStream);
    bool isSupportPlayback();

    int openPlayback(const GBT_RecordUrl& record, double speed, MStreamSourcePtr& streamSource);

    void closeSessions();

    void notifyMediaEnd(InviteSessionHandle handle, const std::string& deviceID);

    int findDeviceId(const char* deviceID);
    
    std::string makeServerUri(const char* deviceID);
    std::string makeServerUri();

    av::RtpMediaChannelPtr createRtpMediaChanne(av::RtpProtocol protocol);

protected:
	comn::CriticalSection   m_cs;

    SipAgent    m_agent;
    GbtDeviceAgentSink* m_sink;
    GbtDeviceMessageHandler*    m_msgHandler;

    CommandHandlerMap   m_cmdHandlerMap;
    GbtMediaDeviceMap   m_deviceMap;
    MediaSessionMap     m_sessionMap;

    GBT_Server  m_server;

    SubscriptionCatalogMap  m_subsCatalogMap;
    SubscriptionAlarmMap    m_subsAlarmMap;
    SubscriptionPositionMap m_subsPositionMap;

    std::shared_ptr< comn::TimerQueue > m_timerQueue;

    std::shared_ptr< HttpServer >   m_httpServer;
	uint16_t	m_httpPort;
	std::string	m_httpUrl;

	GBT_Catalog     m_catalog;
	GBT_Position    m_position;

	std::string	m_contact;

    GbtDevicePlaybackHandler*    m_playbackHandler;

    std::string m_talkName;
    std::string m_hostAddr;

    GBT_Transport   m_sipTransport;

    std::shared_ptr< av::RtpMediaChannelFactory >	m_rtpChannelFactory;

    GBT_Transport   m_talkTransport;


};


} /* namespace gbt */

#endif /* CGBTDEVICEAGENT_H_ */
